package top.wshape1.largefileupload.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.wshape1.largefileupload.domain.vo.CheckFileRespVO;
import top.wshape1.largefileupload.domain.vo.CheckFileVO;
import top.wshape1.largefileupload.domain.vo.UploadFileRespVO;
import top.wshape1.largefileupload.domain.vo.UploadFileVO;
import top.wshape1.largefileupload.service.MinioService;
import top.wshape1.largefileupload.service.UploadService;

import java.io.IOException;
import java.util.UUID;

/**
 * @author Wshape1
 * @version 1.0
 * @description
 * @since 2025-01-24
 */

@Service
@RequiredArgsConstructor
public class UploadServiceImpl implements UploadService {

    private final MinioService minioService;

    @Override
    public UploadFileRespVO UploadFile(UploadFileVO uploadFileVO) {

        UploadFileRespVO uploadFileRespVO;

        try {
            if (uploadFileVO.getChunks() == null) {
                uploadFileRespVO = this.UploadFileDirectly(uploadFileVO);
            } else {
                uploadFileRespVO = this.UploadFileChunk(uploadFileVO);
            }
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败");
        }

        return uploadFileRespVO;
    }

    @Override
    public CheckFileRespVO checkFile(CheckFileVO checkFileVO) {
        String objectName = minioService.checkFile(checkFileVO.getMd5());
        if (objectName != null) {
            return CheckFileRespVO.builder()
                    .exist(true)
                    .url(minioService.generateDownloadUrl(objectName))
                    .build();
        }
        return CheckFileRespVO.builder()
                .exist(false)
                .build();
    }

    private UploadFileRespVO UploadFileChunk(UploadFileVO uploadFileVO) throws IOException {
        // 先检查分片是否上传过
        String chunkObjectName = minioService.checkChunk(uploadFileVO.getMd5(), uploadFileVO.getChunk());

        if (chunkObjectName == null) {
            // 上传分片
            minioService.uploadChunk(uploadFileVO.getMd5(),
                    uploadFileVO.getChunk(),
                    uploadFileVO.getFile().getInputStream());
        }
        UploadFileRespVO vo = UploadFileRespVO.builder()
                .completeUpload(uploadFileVO.getChunk() == uploadFileVO.getChunks() - 1)
                .build();

        if (vo.getCompleteUpload()) {
            // 合并分片
            String finalObjectName = UUID.randomUUID().toString().replace("-", "") + uploadFileVO.getName();
            minioService.mergeChunks(finalObjectName, uploadFileVO.getMd5(), uploadFileVO.getChunks());
            vo.setUrl(minioService.generateDownloadUrl(finalObjectName));
        }

        return vo;
    }

    private UploadFileRespVO UploadFileDirectly(UploadFileVO uploadFileVO) throws IOException {
        String objectName = UUID.randomUUID().toString().replace("-", "") + uploadFileVO.getName();
        minioService.uploadFile(objectName,
                uploadFileVO.getMd5(),
                uploadFileVO.getFile().getInputStream(),
                uploadFileVO.getFile().getContentType());
        return UploadFileRespVO.builder()
                .completeUpload(true)
                .url(minioService.generateDownloadUrl(objectName))
                .build();
    }
}
